﻿using System;
using System.Collections.Generic;
using System.Threading;

// 气象数据类
public class WeatherData
{
    public DateTime LastUpdateTime { get; set; }
    public double Temperature { get; set; }
    public double Humidity { get; set; }
    public double Pressure { get; set; }

    public WeatherData(DateTime time, double temp, double humidity, double pressure)
    {
        LastUpdateTime = time;
        Temperature = temp;
        Humidity = humidity;
        Pressure = pressure;
    }

    public override string ToString()
    {
        return $"[{LastUpdateTime:HH:mm:ss}] 温度: {Temperature:F1}°C, 湿度: {Humidity:F1}%, 气压: {Pressure:F1}hPa";
    }
}

// 观察者接口
public interface IWeatherObserver
{
    void Update(WeatherData data);
}

// 气象站类（被观察者）
public class WeatherStation
{
    private WeatherData currentData;
    private List<IWeatherObserver> observers;

    // 气象数据改变事件
    public event Action<WeatherData> WeatherDataChanged;

    public WeatherStation()
    {
        observers = new List<IWeatherObserver>();
        currentData = new WeatherData(DateTime.Now, 0, 0, 0);
    }

    // 当前气象数据属性
    public WeatherData CurrentData
    {
        get { return currentData; }
        set
        {
            currentData = value;
            OnWeatherDataChanged();
        }
    }

    // 设置新的气象数据
    public void SetWeatherData(double temp, double humidity, double pressure)
    {
        CurrentData = new WeatherData(DateTime.Now, temp, humidity, pressure);
    }

    // 添加观察者
    public void AddObserver(IWeatherObserver observer)
    {
        if (!observers.Contains(observer))
        {
            observers.Add(observer);
        }
    }

    // 移除观察者
    public void RemoveObserver(IWeatherObserver observer)
    {
        observers.Remove(observer);
    }

    // 通知所有观察者
    protected virtual void OnWeatherDataChanged()
    {
        // 调用事件
        WeatherDataChanged?.Invoke(currentData);

        // 调用观察者更新方法
        foreach (var observer in observers)
        {
            observer.Update(currentData);
        }
    }

    // 开始模拟数据采集
    public void StartDataCollection()
    {
        Console.WriteLine("气象站开始数据采集...");
        Random random = new Random();

        // 模拟实时数据更新
        for (int i = 0; i < 10; i++)
        {
            double temp = 15 + random.NextDouble() * 20; // 15-35度
            double humidity = 30 + random.NextDouble() * 50; // 30-80%
            double pressure = 1000 + random.NextDouble() * 50; // 1000-1050hPa

            SetWeatherData(temp, humidity, pressure);
            Thread.Sleep(2000); // 每2秒更新一次
        }
    }
}

// 屏幕显示类
public class ScreenDisplay : IWeatherObserver
{
    private string displayName;

    public ScreenDisplay(string name)
    {
        displayName = name;
    }

    public void Update(WeatherData data)
    {
        Console.WriteLine($"[{displayName}] 更新显示: {data}");
    }

    // 专门的显示方法
    public void DisplayData(WeatherData data)
    {
        Console.WriteLine($"\n=== {displayName} ===");
        Console.WriteLine($"最后更新时间: {data.LastUpdateTime:yyyy-MM-dd HH:mm:ss}");
        Console.WriteLine($"当前温度: {data.Temperature:F1}°C");
        Console.WriteLine($"当前湿度: {data.Humidity:F1}%");
        Console.WriteLine($"当前气压: {data.Pressure:F1}hPa");
        Console.WriteLine("====================\n");
    }
}

// 数据库保存类
public class DatabaseSaver : IWeatherObserver
{
    private List<WeatherData> storedData;
    private string databaseName;

    public DatabaseSaver(string name)
    {
        databaseName = name;
        storedData = new List<WeatherData>();
    }

    public void Update(WeatherData data)
    {
        SaveToDatabase(data);
    }

    public void SaveToDatabase(WeatherData data)
    {
        storedData.Add(data);
        Console.WriteLine($"[{databaseName}] 数据已保存到数据库: {data}");
    }

    public void DisplayStoredData()
    {
        Console.WriteLine($"\n=== {databaseName} - 存储的气象数据 ===");
        foreach (var data in storedData)
        {
            Console.WriteLine(data);
        }
        Console.WriteLine($"总计: {storedData.Count} 条记录");
        Console.WriteLine("================================\n");
    }

    public int GetRecordCount()
    {
        return storedData.Count;
    }
}

// 手机App显示类（额外添加，展示扩展性）
public class MobileAppDisplay : IWeatherObserver
{
    private string appName;

    public MobileAppDisplay(string name)
    {
        appName = name;
    }

    public void Update(WeatherData data)
    {
        Console.WriteLine($"[{appName}推送]  温度: {data.Temperature:F1}°C, 湿度: {data.Humidity:F1}%");
    }
}

class Program
{
    static void Main()
    {
        Console.WriteLine("=== 气象监测系统启动 ===\n");

        // 创建气象站
        WeatherStation weatherStation = new WeatherStation();

        // 创建观察者
        ScreenDisplay mainScreen = new ScreenDisplay("主控屏幕");
        ScreenDisplay lobbyScreen = new ScreenDisplay("大厅显示屏");
        DatabaseSaver database = new DatabaseSaver("气象数据库");
        MobileAppDisplay mobileApp = new MobileAppDisplay("气象通");

        // 注册观察者 - 方式1：使用AddObserver方法
        weatherStation.AddObserver(mainScreen);
        weatherStation.AddObserver(lobbyScreen);
        weatherStation.AddObserver(database);
        weatherStation.AddObserver(mobileApp);

        // 注册观察者 - 方式2：使用事件
        weatherStation.WeatherDataChanged += (data) =>
        {
            Console.WriteLine($"[事件通知] 气象数据已更新: {data.LastUpdateTime:HH:mm:ss}");
        };

        // 测试初始数据
        Console.WriteLine("=== 测试初始数据 ===");
        weatherStation.SetWeatherData(25.5, 65.2, 1013.5);

        // 手动更新数据测试
        Console.WriteLine("\n=== 手动更新数据测试 ===");
        weatherStation.SetWeatherData(26.8, 62.1, 1012.8);

        // 使用屏幕显示类的专门显示方法
        Console.WriteLine("\n=== 专门显示测试 ===");
        mainScreen.DisplayData(weatherStation.CurrentData);

        // 模拟实时数据采集
        Console.WriteLine("=== 开始模拟实时数据采集 ===");
        weatherStation.StartDataCollection();

        // 显示数据库存储的所有数据
        database.DisplayStoredData();

        // 测试移除观察者
        Console.WriteLine("=== 测试移除观察者 ===");
        weatherStation.RemoveObserver(lobbyScreen);
        weatherStation.SetWeatherData(28.3, 58.7, 1011.2);
        Console.WriteLine("大厅显示屏已移除，不再显示更新");

        // 最终状态
        Console.WriteLine("=== 系统最终状态 ===");
        Console.WriteLine($"数据库中共存储了 {database.GetRecordCount()} 条气象记录");
        Console.WriteLine("=== 气象监测系统结束 ===\n");
    }
}